#include "stm32f10x.h"
uint16_t LEFT_PIN1 = GPIO_Pin_4;
uint16_t  LEFT_PIN2  = GPIO_Pin_5;
uint16_t   RIGHT_PIN1 = GPIO_Pin_6;
uint16_t    RIGHT_PIN2 = GPIO_Pin_7;
uint8_t Car_Speed = 0;
uint8_t Car_Speed_Step = 20;

void Car_Init_Left(void)
{
    // 1. init pwm
    // 1.1 enable rcc-tim2
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    // 1.2 enable rcc-gpioa,init gpioa2
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_InitTypeDef GPIO_InitParam;
    GPIO_InitParam.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitParam.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitParam.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitParam);
    

    // 1.3 select clock input mode
    TIM_InternalClockConfig(TIM2);
    // 1.4 configure base-time unit
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitParam;
    TIM_TimeBaseInitParam.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitParam.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitParam.TIM_Period = 100 - 1;
    TIM_TimeBaseInitParam.TIM_Prescaler = 72 - 1; // 72 * 1000 * 1000 / 100 / 72 =10khz
    TIM_TimeBaseInitParam.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitParam);
    // 1.5 configure output compare
    TIM_OCInitTypeDef TIM_OCInitParam;
    TIM_OCStructInit(&TIM_OCInitParam);
    TIM_OCInitParam.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitParam.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitParam.TIM_OutputState = TIM_OutputState_Enable;
    // cr
    TIM_OCInitParam.TIM_Pulse = Car_Speed;

    TIM_OC3Init(TIM2, &TIM_OCInitParam);
    // 1.6 enable tim2
    TIM_Cmd(TIM2, ENABLE);

    // 2. init gpioa4 gpioa5
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_InitParam.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitParam.GPIO_Pin = LEFT_PIN1 | LEFT_PIN2;
    GPIO_InitParam.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitParam);

}
void Car_Init_Right(void)
{

    // 1. init pwm
    // 1.1 enable rcc-tim2
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    // 1.2 enable rcc-gpioa,init gpioa2
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_InitTypeDef GPIO_InitParam;
    GPIO_InitParam.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitParam.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitParam.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitParam);
    

    // 1.3 select clock input mode
    TIM_InternalClockConfig(TIM2);
    // 1.4 configure base-time unit
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitParam;
    TIM_TimeBaseInitParam.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitParam.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitParam.TIM_Period = 100 - 1;
    TIM_TimeBaseInitParam.TIM_Prescaler = 72 - 1; // 72 * 1000 * 1000 / 100 / 72 =10khz
    TIM_TimeBaseInitParam.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitParam);
    // 1.5 configure output compare
    TIM_OCInitTypeDef TIM_OCInitParam;
    TIM_OCStructInit(&TIM_OCInitParam);
    TIM_OCInitParam.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitParam.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitParam.TIM_OutputState = TIM_OutputState_Enable;
    // cr
    TIM_OCInitParam.TIM_Pulse = Car_Speed;

    TIM_OC1Init(TIM2, &TIM_OCInitParam);
    // 1.6 enable tim2
    TIM_Cmd(TIM2, ENABLE);

    // 2. init gpioa4 gpioa5
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_InitParam.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitParam.GPIO_Pin = RIGHT_PIN1 | RIGHT_PIN2;
    GPIO_InitParam.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitParam);
}

void Car_Init(void)
{
    Car_Init_Left();
    Car_Init_Right();

}
void Car_Speed_Left_Set(uint8_t Speed)
{
    if (Speed > 100)
    {
        Speed = 100;
    }
    if (Speed < 0)
    {
        Speed = 0;
    }
    TIM_SetCompare3(TIM2, Speed);

}
void Car_Speed_Right_Set(uint8_t Speed)
{
    if (Speed > 100)
    {
        Speed = 100;
    }
    if (Speed < 0)
    {
        Speed = 0;
    }
    TIM_SetCompare1(TIM2, Speed);

}

void Car_Speed_Set(uint8_t Speed)
{
    if (Speed > 100)
    {
        Speed = 100;
    }
    if (Speed < 0)
    {
        Speed = 0;
    }
    Car_Speed = Speed;
    TIM_SetCompare1(TIM2, Car_Speed);
    TIM_SetCompare3(TIM2, Car_Speed);
}

void Car_Speed_Up(void)
{
    Car_Speed_Set(Car_Speed + 20);
}

void Car_Speed_Down(void)
{

    Car_Speed_Set(Car_Speed - 20);
}

void Car_Turn_Left(void)
{
    if (Car_Speed == 0)
    {
        Car_Speed = 20;
    }
    Car_Speed_Right_Set(0);
    Car_Speed_Left_Set(Car_Speed);

}

void Car_Turn_Right(void)
{
    if (Car_Speed == 0)
    {
        Car_Speed = 20;
    }
    Car_Speed_Right_Set(Car_Speed);
    Car_Speed_Left_Set(0);
}

void Car_Foward(void)
{
    GPIO_SetBits(GPIOA, GPIO_Pin_4);
    GPIO_ResetBits(GPIOA, GPIO_Pin_5);
    GPIO_SetBits(GPIOA, GPIO_Pin_6);
    GPIO_ResetBits(GPIOA, GPIO_Pin_7);
    if (Car_Speed = 0)
    {
        Car_Speed = 20;
    }
    Car_Speed_Set(Car_Speed);
}

void Car_Backward(void)
{
    GPIO_SetBits(GPIOA, GPIO_Pin_5);
    GPIO_ResetBits(GPIOA, GPIO_Pin_4);
    GPIO_SetBits(GPIOA, GPIO_Pin_6);
    GPIO_ResetBits(GPIOA, GPIO_Pin_7);
    Car_Speed_Set(20);
}